package com.sh.apibackend.controller;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.gson.Gson;
import com.sh.apibackend.annotation.AuthCheck;
import com.sh.apibackend.common.*;
import com.sh.apibackend.constant.CommonConstant;
import com.sh.apibackend.exception.BusinessException;
import com.sh.apibackend.model.dto.interfaceinfo.InterfaceInfoAddRequest;
import com.sh.apibackend.model.dto.interfaceinfo.InterfaceInfoInvokeRequest;
import com.sh.apibackend.model.dto.interfaceinfo.InterfaceInfoQueryRequest;
import com.sh.apibackend.model.dto.interfaceinfo.InterfaceInfoUpdateRequest;
import com.sh.apibackend.model.enums.InterfaceInfoStateEnum;
import com.sh.apibackend.model.vo.InterfaceInfoVo;
import com.sh.apibackend.service.InterfaceChargingService;
import com.sh.apibackend.service.InterfaceInfoService;
import com.sh.apibackend.service.UserInterfaceInfoService;
import com.sh.apibackend.service.UserService;
import com.sh.apibackend.utils.JwtUtils;
import com.sh.apiclientsdk.client.NameApiClient;
import com.sh.apicommon.entity.InterfaceCharging;
import com.sh.apicommon.entity.InterfaceInfo;
import com.sh.apicommon.entity.User;
import com.sh.apicommon.entity.UserInterfaceInfo;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * API接口
 *
 */
@RestController
@RequestMapping("apibackend/interfaceInfo")
@Slf4j
public class InterfaceInfoController {
    // 用户接口信息
    @Resource
    private InterfaceInfoService interfaceInfoService;

    // 充值接口
    @Resource
    private InterfaceChargingService interfaceChargingService;

    @Resource
    private UserInterfaceInfoService userInterfaceInfoService;

    @Resource
    private UserService userService;

    private static final String SDK_PER="com.sh.apiclientsdk.client.";

    // region 业务逻辑


    /**
     * 获取sdk文件
     */
    @GetMapping("/sdk")
    public void getSdk(HttpServletResponse response) throws IOException {
        // 获取要下载的文件
        org.springframework.core.io.Resource resource = new ClassPathResource("api-client-sdk-0.0.1.jar");
        InputStream inputStream = resource.getInputStream();

        // 设置响应头
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment; filename=api-client-sdk-0.0.1.jar");

        // 将文件内容写入响应
        try (OutputStream out = response.getOutputStream()) {
            byte[] buffer = new byte[4096];
            int length;
            while ((length = inputStream.read(buffer)) > 0) {
                out.write(buffer, 0, length);
            }
            out.flush();
        } catch (IOException e) {
            // 处理异常
            e.printStackTrace();
        } finally {
            inputStream.close();
        }
    }



    /**
     *  在线调用接口
     * @param interfaceInfoInvokeRequest
     * @param request
     * @return
     */
    @PostMapping("/invoke")
    public BaseResponse<Object> invokeInterfaceInfo(@RequestBody InterfaceInfoInvokeRequest interfaceInfoInvokeRequest,
                                                    HttpServletRequest request) {
        //1.判断请求中'接口id'是否存在
        if (interfaceInfoInvokeRequest == null || interfaceInfoInvokeRequest.getId() == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        long id = interfaceInfoInvokeRequest.getId();
        // 判断数据库中 '接口' 是否存在
        InterfaceInfo interfaceInfo = interfaceInfoService.getById(id);    // 根据id查询数据库中接口
        if (interfaceInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }

        User loginUser = userService.getLoginUser(request);
        String accessKey = loginUser.getAccessKey();
        String secretKey = loginUser.getSecretKey();

        //2.用户调用次数校验
        QueryWrapper<UserInterfaceInfo> userInterfaceInfoQueryWrapper = new QueryWrapper<>();
        userInterfaceInfoQueryWrapper.eq("userId", loginUser.getId());
        userInterfaceInfoQueryWrapper.eq("interfaceInfoId", id);
        UserInterfaceInfo userInterfaceInfo = userInterfaceInfoService.getOne(userInterfaceInfoQueryWrapper);
        if (userInterfaceInfo == null){
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "调用次数不足！");
        }
        int leftNum = userInterfaceInfo.getLeftNum();
        if(leftNum <= 0){
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "调用次数不足！");
        }

        //3.发起接口调用
        String requestParams= interfaceInfoInvokeRequest.getUserRequestParams();    // 获取用户请求参数
        // 这里面调用                                   sdk地址                                方法名称                  请求参数  用户的accessKey 用户的secretKey
         Object res = invokeInterfaceInfo(interfaceInfo.getSdk(), interfaceInfo.getName(), requestParams, accessKey, secretKey);
//        NameApiClient nameApiClient = new NameApiClient(accessKey, secretKey);
//        com.sh.apiclientsdk.model.User user = new Gson().fromJson(requestParams, com.sh.apiclientsdk.model.User.class);
//        String res = nameApiClient.getName(user);
        if (res == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        if (res.toString().contains("Error request")) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "调用错误，请检查请求！");
        }
        return ResultUtils.success(res);
    }

    /**
     * 放射调用接口
     * @param classPath     com.sh.apiclientsdk.client.NameApiClient
     * @param methodName    getName
     * @param userRequestParams    {"name":"张三"}
     * @param accessKey             xxxx
     * @param secretKey             xxxx
     * @return
     */
    private Object invokeInterfaceInfo(String classPath,
                                       String methodName,
                                       String userRequestParams,
                                       String accessKey,
                                       String secretKey) {
        try {
            Class<?> clientClazz = Class.forName(classPath);
            // 1. 获取构造器，参数为ak,sk
            Constructor<?> binApiClientConstructor = clientClazz.getConstructor(String.class, String.class);
            // 2. 构造出客户端
            Object apiClient =  binApiClientConstructor.newInstance(accessKey, secretKey);

            // 3. 找到要调用的方法
            Method[] methods = clientClazz.getMethods();
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    // 3.1 获取参数类型列表
                    Class<?>[] parameterTypes = method.getParameterTypes();
                    if (parameterTypes.length == 0) {
                        // 如果没有参数，直接调用
                        return method.invoke(apiClient);
                    }
                    Gson gson = new Gson();
                    // 构造参数
                    Object parameter = gson.fromJson(userRequestParams, parameterTypes[0]);
                    return method.invoke(apiClient, parameter);
                }
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "找不到调用的方法!! 请检查你的请求参数是否正确!");
        }
    }


    /**
     * 上线
     */
    @PostMapping("/online")
    @AuthCheck(mustRole = "admin")
    public BaseResponse<Boolean> onlineInterfaceInfo(@RequestBody IdRequest idRequest, HttpServletRequest request) {
        if ( idRequest==null || idRequest.getId()==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        long id = idRequest.getId();
        InterfaceInfo interfaceInfo = interfaceInfoService.getById(id);
        if (interfaceInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        // todo 校验接口是否可以调用

        InterfaceInfo updateInterfaceInfo = new InterfaceInfo();
        updateInterfaceInfo.setId(id);
        updateInterfaceInfo.setStatus(InterfaceInfoStateEnum.online.getValue());
        boolean result = interfaceInfoService.updateById(updateInterfaceInfo);
        return ResultUtils.success(result);
    }


    /**
     * 下线
     */
    @PostMapping("/offline")
    @AuthCheck(mustRole = "admin")
    public BaseResponse<Boolean> offlineInterfaceInfo(@RequestBody IdRequest idRequest, HttpServletRequest request){
        if ( idRequest==null || idRequest.getId()==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        long id = idRequest.getId();
        InterfaceInfo oldInterfaceInfo = interfaceInfoService.getById(id);
        if (oldInterfaceInfo == null){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"要下线的接口不存在!");
        }
        InterfaceInfo interfaceInfo = new InterfaceInfo();
        interfaceInfo.setId(id);
        interfaceInfo.setStatus(InterfaceInfoStateEnum.offline.getValue());
        boolean b = interfaceInfoService.updateById(interfaceInfo);
        return ResultUtils.success(b);
    }


    /**
     * 根据 id 获取
     * @param id
     * @return
     */
    @GetMapping("/get")
    public BaseResponse<InterfaceInfoVo> getInterfaceInfoById(long id, HttpServletRequest request) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long userId = JwtUtils.getUserIdByToken(request);
        if (userId == null){
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        InterfaceInfo interfaceInfo = interfaceInfoService.getById(id);
        // 获取接口的收费规则
        InterfaceCharging interfaceCharging = interfaceChargingService.getOne(new QueryWrapper<InterfaceCharging>().eq("interfaceId", id));
        InterfaceInfoVo interfaceInfoVO = new InterfaceInfoVo();
        BeanUtils.copyProperties(interfaceInfo, interfaceInfoVO);
        if (interfaceCharging != null) {
            //获取付费剩余调用次数
            interfaceInfoVO.setCharging(interfaceCharging.getCharging());
//            interfaceInfoVO.setAvailablePieces(interfaceCharging.getAvailablePieces());
            interfaceInfoVO.setChargingId(interfaceCharging.getId());
        }
        //看看当前用户这个接口剩余调用次数
        QueryWrapper<UserInterfaceInfo> userInterfaceInfoQueryWrapper = new QueryWrapper<>();
        userInterfaceInfoQueryWrapper.eq("userId",userId);
        userInterfaceInfoQueryWrapper.eq("interfaceInfoId", id);
        UserInterfaceInfo userInterfaceInfo = userInterfaceInfoService.getOne(userInterfaceInfoQueryWrapper);
        if (userInterfaceInfo!=null){
            // 剩余调用次数
            interfaceInfoVO.setAvailablePieces(userInterfaceInfo.getLeftNum().toString());
        }
        return ResultUtils.success(interfaceInfoVO);
    }


    // endregion


    // region 增删改查

    /**
     * 新增
     */
    @PostMapping("/add")
    public BaseResponse<Long> addInterfaceInfo(@RequestBody InterfaceInfoAddRequest interfaceInfoAddRequest, HttpServletRequest request){
        if ( interfaceInfoAddRequest ==null ){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        InterfaceInfo interfaceInfo = new InterfaceInfo();
        BeanUtils.copyProperties(interfaceInfoAddRequest, interfaceInfo);
        interfaceInfoService.validInterfaceInfo(interfaceInfo, true);   // 校验  并且创建参数不能为空
        User loginUser = userService.getLoginUser(request);   // 从redis里面拿到当前用户
        interfaceInfo.setUserId(loginUser.getId());   // 谁添加的
//        interfaceInfo.setSdk(SDK_PER+interfaceInfoAddRequest.getSdk());
        interfaceInfo.setSdk(interfaceInfoAddRequest.getSdk());
        boolean result = interfaceInfoService.save(interfaceInfo);    // 保存到数据库
        if (!result) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }
        long newInterfaceInfoId = interfaceInfo.getId();
        return ResultUtils.success(newInterfaceInfoId);
    }

    /**
     * 删除
     */
    @PostMapping("/delete")
    public BaseResponse<Boolean> deleteInterfaceInfo(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request){
        if (deleteRequest == null || deleteRequest.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);   // 从redis里面拿到当前用户
        Long id = deleteRequest.getId();  // 要删除的接口id
        InterfaceInfo oldInterfaceInfo = interfaceInfoService.getById(id);   // 根据id查询数据库中接口信息
        if (oldInterfaceInfo==null){   // 判断要删除的接口id是否为空
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        Long userId = oldInterfaceInfo.getUserId();   // 获取接口所属用户id  创建人
        if ( !loginUser.getId().equals(userId) && !userService.isAdmin(request) ){  // 如果不是创建人
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }

        boolean b = interfaceInfoService.removeById(id);
        return ResultUtils.success(b);
    }


    /**
     * 修改
     */
    @PostMapping("/update")
    public BaseResponse<Boolean> updateInterfaceInfo(@RequestBody InterfaceInfoUpdateRequest interfaceInfoUpdateRequest, HttpServletRequest request){
       if (interfaceInfoUpdateRequest == null || interfaceInfoUpdateRequest.getId() <=0) {
           throw new BusinessException(ErrorCode.PARAMS_ERROR);
       }
        InterfaceInfo interfaceInfo = new InterfaceInfo();
        BeanUtils.copyProperties(interfaceInfoUpdateRequest, interfaceInfo);
        // 校验
        interfaceInfoService.validInterfaceInfo(interfaceInfo, false);
        User user = userService.getLoginUser(request);   // 执行修改的用户
        Long id = interfaceInfoUpdateRequest.getId();// 接口id
        InterfaceInfo oldInterfaceInfo = interfaceInfoService.getById(id);
        if ( oldInterfaceInfo==null ){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        if ( !oldInterfaceInfo.getUserId().equals(user.getId()) || !userService.isAdmin(request)){
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        boolean result = interfaceInfoService.updateById(interfaceInfo);
        return ResultUtils.success(result);
    }

    /**
     * 分页获取列表
     * @param interfaceInfoQueryRequest
     * @param request
     * @return
     */
    @GetMapping("/list/page")
    public BaseResponse<Page<InterfaceInfoVo>> listInterfaceInfoByPage(InterfaceInfoQueryRequest interfaceInfoQueryRequest,
                                                                       HttpServletRequest request) {
        if (interfaceInfoQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        InterfaceInfo interfaceInfoQuery = new InterfaceInfo();
        BeanUtils.copyProperties(interfaceInfoQueryRequest, interfaceInfoQuery);
        long current = interfaceInfoQueryRequest.getCurrent();
        long size = interfaceInfoQueryRequest.getPageSize();
        String sortField = interfaceInfoQueryRequest.getSortField();
        String sortOrder = interfaceInfoQueryRequest.getSortOrder();
        String description = interfaceInfoQuery.getDescription();
        // content 需支持模糊搜索
        interfaceInfoQuery.setDescription(null);
        // 限制爬虫
        if (size > 50) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        QueryWrapper<InterfaceInfo> queryWrapper = new QueryWrapper<>(interfaceInfoQuery);
        queryWrapper.like(StringUtils.isNotBlank(description), "content", description);
        queryWrapper.orderBy(StringUtils.isNotBlank(sortField),
                sortOrder.equals(CommonConstant.SORT_ORDER_ASC), sortField);
        Page<InterfaceInfo> interfaceInfoPage = interfaceInfoService.page(new Page<>(current, size), queryWrapper);
        // todo连接查询
        Page<InterfaceInfoVo> interfaceInfoVoPage = new Page<>();
        ArrayList<InterfaceInfoVo> list = new ArrayList<>();
        for (int l = 0; l < interfaceInfoPage.getRecords().size(); l++) {
            QueryWrapper<InterfaceCharging> chargingQueryWrapper = new QueryWrapper<>();
            chargingQueryWrapper.eq("interfaceId", interfaceInfoPage.getRecords().get(l).getId());
            InterfaceCharging one = interfaceChargingService.getOne(chargingQueryWrapper);
            InterfaceInfoVo interfaceInfoVo = new InterfaceInfoVo();
            BeanUtils.copyProperties(interfaceInfoPage.getRecords().get(l), interfaceInfoVo);
            if (one != null){
                interfaceInfoVo.setCharging(one.getCharging());
            }else {
                interfaceInfoVo.setCharging(0d);
            }
            list.add(interfaceInfoVo);
        }
        interfaceInfoVoPage.setRecords(list);
        interfaceInfoVoPage.setTotal(interfaceInfoPage.getTotal());
        return ResultUtils.success(interfaceInfoVoPage);
    }



    /**
     * 获取列表（仅管理员可使用）
     * @param interfaceInfoQueryRequest
     * @return
     */
    @AuthCheck(mustRole = "admin")
    @GetMapping("/list")
    public BaseResponse<List<InterfaceInfo>> listInterfaceInfo(InterfaceInfoQueryRequest interfaceInfoQueryRequest) {
        InterfaceInfo interfaceInfoQuery = new InterfaceInfo();
        if (interfaceInfoQueryRequest != null) {
            BeanUtils.copyProperties(interfaceInfoQueryRequest, interfaceInfoQuery);
        }
        QueryWrapper<InterfaceInfo> queryWrapper = new QueryWrapper<>(interfaceInfoQuery);
        List<InterfaceInfo> interfaceInfoList = interfaceInfoService.list(queryWrapper);
        return ResultUtils.success(interfaceInfoList);
    }

// endregion






}
